//
//  CQExtralTagSeletedCollectionView.m
//  CJUIKitDemo
//
//  Created by ciyouzen on 2017/9/11.
//  Copyright © 2017年 dvlproad. All rights reserved.
//

#import "CQExtralTagSeletedCollectionView.h"
#import "CQTagLookCollectionViewCell.h"
#import "CQTagActionCollectionViewCell.h"
#import "CQTagAddCollectionViewCell.h"
#import <CJCollectionViewDataSource/CJExtralItemCollectionViewDataSource.h>
#import <CJCollectionViewLayout/CJCellWaterLayout.h>

@interface CQExtralTagSeletedCollectionView () <UICollectionViewDelegateFlowLayout, UICollectionViewDelegate> {
    
}
@property (nonatomic, strong, readonly) CJExtralItemCollectionViewDataSource *mDataSource;

@property (nonatomic, copy, readonly) NSString *(^textFormatBlock)(NSString *originText); /**< 将text格式化的方法（比如传入省市，但我们只想显示市），默认nil，表示使用原值显示 */
@property (nonatomic, copy, readonly) void(^addTagBlock)(CQExtralTagSeletedCollectionView *bCollectionView, NSIndexPath *indexPath);      /**< 添加tag的方法 */
@property (nonatomic, copy, readonly) void(^updateTagBlock)(CQExtralTagSeletedCollectionView *bCollectionView, NSIndexPath *indexPath, NSString *oldTagString);   /**< 更新tag的方法 */

@property (nonatomic, assign) NSIndexPath *oldSelectedIndexPath;    /**< 旧选中的indexPath */

@property (nonatomic, copy, readonly) void(^ _Nullable tagChangeBlock)(NSMutableArray<CJTagSectionDataModel *> *tagSectionModels, NSIndexPath *indexPath);
@property (nonatomic, copy, readonly) void(^selectedTagChangeBlock)(NSArray<NSString *> *tagNames);

@end


@implementation CQExtralTagSeletedCollectionView

/*
 *  初始化标签视图
 *
 *  @param itemHorizontalSpacing    两个item之间的水平间距
 *  @param itemVerticalSpacing      两个item之间的竖直间距
 *  @param sectionLeftRightInset    每个section左右离边缘的间距
 *  @param sectionSpacing           两个section之间的间距
 *  @param sectionSettingBlock      根据需要设置每个section。（当某个section的这个block①为nil时,该区个数无限制且无额外item,即显示实际个数；②为非nil时,该区个数可限制且可设置个数未超限时,额外item的位置(当有个数限制且超过后，+号会隐藏)）
 *  @param textFormatBlock          将text格式化的方法（比如传入省市，但我们只想显示市），默认nil，表示使用原值显示
 *  @param addTagBlock              添加tag的方法
 *  @param updateTagBlock           更新所添加的tag的文本方法
 *
 *  @return 标签视图
 */
- (instancetype)initWithItemHorizontalSpacing:(CGFloat)itemHorizontalSpacing
                          itemVerticalSpacing:(CGFloat)itemVerticalSpacing
                        sectionLeftRightInset:(CGFloat)sectionLeftRightInset
                               sectionSpacing:(CGFloat)sectionSpacing
                          sectionSettingBlock:(CJDataSourceSettingModel* (^ _Nullable)(NSInteger section))sectionSettingBlock
                              textFormatBlock:(NSString *(^ _Nullable)(NSString *originText))textFormatBlock
                                  addTagBlock:(void(^)(CQExtralTagSeletedCollectionView *bCollectionView, NSIndexPath *indexPath))addTagBlock
                               updateTagBlock:(void(^)(CQExtralTagSeletedCollectionView *bCollectionView, NSIndexPath *indexPath, NSString *oldTagString))updateTagBlock
{
    CJCellWaterLayout *layout = [[CJCellWaterLayout alloc] init];
    layout.minimumInteritemSpacing = itemHorizontalSpacing;
    layout.minimumLineSpacing = itemVerticalSpacing;
    layout.sectionInset = UIEdgeInsetsMake(0, sectionLeftRightInset, sectionSpacing, sectionLeftRightInset);
    self = [super initWithFrame:CGRectZero collectionViewLayout:layout];
    
    if (self) {
        _textFormatBlock = textFormatBlock;
        _addTagBlock = addTagBlock;
        _updateTagBlock = updateTagBlock;
        
        _tagSectionModels = [[NSMutableArray alloc] init];
        
        [self setupConfigureWithSectionSettingBlock:sectionSettingBlock];
        
    }
    return self;
}


- (void)setupConfigureWithSectionSettingBlock:(CJDataSourceSettingModel* (^ _Nullable)(NSInteger section))sectionSettingBlock {
    self.backgroundColor = [UIColor clearColor];
    self.allowsMultipleSelection = YES; // 开启多选，修复点击自定义cell的时候，之前的cell被取消选中的情况
    
    //以下值，可选设置
    //self.allowsMultipleSelection = YES; //是否打开多选
    
    /* 设置Register的Cell或Nib */
    [self registerClass:[CQTagLookCollectionViewCell class] forCellWithReuseIdentifier:@"normalCell"];
    [self registerClass:[CQTagActionCollectionViewCell class] forCellWithReuseIdentifier:@"editCell"];
    [self registerClass:[CQTagAddCollectionViewCell class] forCellWithReuseIdentifier:@"addCell"];
    
    /* 创建DataSource */
    CJExtralItemCollectionViewDataSource *mDataSource = [[CJExtralItemCollectionViewDataSource alloc] initWithSectionSettingBlock:sectionSettingBlock cellForItemAtIndexPathBlock:^UICollectionViewCell *(UICollectionView *collectionView, NSIndexPath *indexPath, BOOL isExtralItem) {
        if (!isExtralItem) {
            CQTagModel *tagModel = [self.mDataSource dataModelAtIndexPath:indexPath];
            if (tagModel.editEnable == NO) {
                CQTagLookCollectionViewCell *dataCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"normalCell" forIndexPath:indexPath];
                dataCell.shouldNormalAndSelectedSame = NO;
                
                NSString *cellText = tagModel.name;
                if (self.textFormatBlock) {
                    cellText = self.textFormatBlock(tagModel.name);
                }
                dataCell.text = cellText;
                
                return dataCell;
            } else {
                CQTagActionCollectionViewCell *editCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"editCell" forIndexPath:indexPath];
                editCell.editHandle = ^{
                    if (self.updateTagBlock) {
                        self.updateTagBlock(self, indexPath, tagModel.name);
                    }
                };

                NSString *cellText = tagModel.name;
                if (self.textFormatBlock) {
                    cellText = self.textFormatBlock(tagModel.name);
                }
                editCell.text = cellText;
                
                return editCell;
            }
            
        } else {
            CQTagAddCollectionViewCell *extralCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"addCell" forIndexPath:indexPath];
            extralCell.textLabel.text = NSLocalizedString(@"自定义", nil);
            return extralCell;
        }
    }];
    _mDataSource = mDataSource;
    
    
    
    /* 设置DataSource和Delegate */
    self.dataSource = self.mDataSource;
    self.delegate = self;
}


/*
 *  设置回调
 *
 *  @param tagChangeBlock           tag内容改变的回调(会同时触发selectedTagChangeBlock。indexPath：在哪个位置新增，或者在哪个位置修改)
 *  @param selectedTagChangeBlock   选中的tag改变的回调
 */
- (void)setupTagChangeBlock:(void(^ _Nullable)(NSMutableArray<CJTagSectionDataModel *> *tagSectionModels, NSIndexPath *indexPath))tagChangeBlock
     selectedTagChangeBlock:(void(^ _Nonnull)(NSArray<NSString *> *tagNames))selectedTagChangeBlock
{
    _tagChangeBlock = tagChangeBlock;
    _selectedTagChangeBlock = selectedTagChangeBlock;
}

#pragma mark - Event
/// 添加标签及其内容
- (void)addTagString:(NSString *)tagString indexPath:(NSIndexPath *)indexPath {
    CJTagSectionDataModel *sectionModel = self.mDataSource.sectionModels[indexPath.section];
    NSMutableArray *tagModels = sectionModel.values;
    
    CJDataSourceSettingModel *settingModel = self.mDataSource.sectionSettingBlock(indexPath.section);
    NSInteger maxDataModelShowCount = settingModel.maxDataModelShowCount;
    if (tagModels.count >= maxDataModelShowCount) {
        NSAssert(NO, @"个数已满，无法再添加，如果你是要更新，请调用另一个方法updateTagString");
    }
    if (tagString.length == 0) {
        return;
    }
    CQTagModel *tagModel = [[CQTagModel alloc] init];
    tagModel.name = tagString;
    tagModel.editEnable = YES;
    
    [tagModels addObject:tagModel];
    [self reloadItemsAtIndexPaths:@[indexPath]];
    
    !self.tagChangeBlock ?: self.tagChangeBlock(self.tagSectionModels, indexPath);
    
    // 触发 selectedTagChangeBlock
    [self __updateSelectedIndexPath:indexPath];
}

/// 更新标签内容
- (void)updateTagString:(NSString *)tagString indexPath:(NSIndexPath *)indexPath {
    if (tagString.length == 0) {
        return;
    }
    CQTagModel *tagModel = [self.mDataSource dataModelAtIndexPath:indexPath];
    tagModel.name = tagString;
    _selectedTagNames = @[tagModel.name];

    [self reloadItemsAtIndexPaths:@[indexPath]];
    [self selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
    
    !self.tagChangeBlock ?: self.tagChangeBlock(self.tagSectionModels, indexPath);
    
    // 触发 selectedTagChangeBlock
    // 2、indexPath即使一样，tag也可能被更新了
    NSString *newTagName = tagString;
    _selectedTagNames = @[newTagName];
    !self.selectedTagChangeBlock ?: self.selectedTagChangeBlock(self.selectedTagNames);
}


#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat cellHeight = 34;
    
    CGFloat cellWidth = 0;
    
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
    CGFloat width = CGRectGetWidth(collectionView.frame);
    CGFloat cellSmallWidth = (width - layout.sectionInset.left - layout.sectionInset.right - 2*layout.minimumInteritemSpacing)/3;
    cellSmallWidth = floor(cellSmallWidth);
    
    
    BOOL isExtralItem = [self.mDataSource isExtraItemIndexPath:indexPath];
    if (isExtralItem) {
        cellWidth = cellSmallWidth;
    } else {
        CQTagModel *tagModel = [self.mDataSource dataModelAtIndexPath:indexPath];
        if (tagModel.editEnable == NO) {
            cellWidth = cellSmallWidth;
        } else {
            cellWidth = [CQTagActionCollectionViewCell cellWidthText:tagModel.name cellHeight:cellHeight showEdit:YES];
            cellWidth = MAX(cellSmallWidth, cellWidth);
            cellWidth = MIN(200, cellWidth); // 限制最大长度(约10个字)
            
            CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
            CGFloat titleLabelMaxWidth = screenWidth - 2 * 36 - 43;
            cellWidth = MIN(cellWidth, titleLabelMaxWidth);
        }
    }
    
    return CGSizeMake(cellWidth, cellHeight);
}


#pragma mark - Setter
/*
 *  设置不能编辑的标签和默认选中的标签(会自动调用reloadData)
 *
 *  @param unableEditTagSectionStrings  设置不能编辑的标签
 *  @param defaultSelectTagString       默认选中的标签
 */
- (void)configUnableEditTagSectionStrings:(NSArray<NSArray<NSString *> *> *)unableEditTagSectionStrings
                   defaultSelectTagString:(nullable NSString *)defaultSelectTagString
{
    NSIndexPath *defaultSelectedIndexPath = nil; // 默认不选择
    
    NSInteger sectionCount = unableEditTagSectionStrings.count;
    for (NSInteger section = 0; section < sectionCount; section++) {
        CJTagSectionDataModel *sectionModel = [[CJTagSectionDataModel alloc] init];
        
        NSArray<NSString *> *unableEditTagStrings = unableEditTagSectionStrings[section];
        NSMutableArray<CQTagModel *> *tagModels = [[NSMutableArray alloc] init];
        NSInteger tagCount = unableEditTagStrings.count;
        for (NSInteger i = 0; i < tagCount; i++) {
            NSString *tagString = unableEditTagStrings[i];
            CQTagModel *tagModel = [[CQTagModel alloc] init];
            tagModel.name = tagString;
            tagModel.editEnable = NO;
            if (tagString.length > 0 && [tagString isEqualToString:defaultSelectTagString]) {
                defaultSelectedIndexPath = [NSIndexPath indexPathForItem:i inSection:section];
            }
            [tagModels addObject:tagModel];
        }
        sectionModel.values = tagModels;
        
        [self.tagSectionModels addObject:sectionModel];
    }
    
    
    if (defaultSelectTagString != nil && defaultSelectTagString.length > 0 && defaultSelectedIndexPath == nil) { // 如果有选中值，但该值却没在已有的固定不变的数组范围内，则将该值添加到新section中
        // 放进section1 中
        NSInteger currentSection = 1;
        CJTagSectionDataModel *sectionModel = [self.tagSectionModels objectAtIndex:currentSection];
        
        CQTagModel *tagModel = [[CQTagModel alloc] init];
        tagModel.name = defaultSelectTagString;
        tagModel.editEnable = YES;
        [sectionModel.values addObject:tagModel];
        
        defaultSelectedIndexPath = [NSIndexPath indexPathForItem:0 inSection:currentSection];;
    }
    
    self.mDataSource.sectionModels = self.tagSectionModels;
    
    if (defaultSelectedIndexPath != nil) {
        [self __updateSelectedIndexPath:defaultSelectedIndexPath];
    }
}

#pragma mark - Update
/*
 *  更新section的设置
 *
 *  @param sectionSettingBlock                  集合视图的每个section的设置(可为nil，为nil表示无个数限制，且无额外item)
 */
- (void)updateSectionSettingBlock:(CJDataSourceSettingModel* (^ _Nullable)(NSInteger section))sectionSettingBlock {
    [self.mDataSource updateSectionSettingBlock:sectionSettingBlock];
}


#pragma mark - UICollectionViewDelegate
// 此点击部分请在子类中实现
////“点到”item时候执行的时间(allowsMultipleSelection为默认的NO的时候，只有选中，而为YES的时候有选中和取消选中两种操作)
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    BOOL isExtralItem = [self.mDataSource isExtraItemIndexPath:indexPath];
    if (isExtralItem) {
        if (self.addTagBlock) {
            self.addTagBlock(self, indexPath);
        }
    } else {
        [self __updateSelectedIndexPath:indexPath];
    }
}

- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    if ([cell isKindOfClass:[CQTagLookCollectionViewCell class]]
        || [cell isKindOfClass:[CQTagActionCollectionViewCell class]])
    {
        // 禁用deselect,防止点击同一个导致该cell被取消。且只禁用 tag 的 lookcell 和 actioncell 的取消选中操作，
        // 而对于 addCell 则不管是选中还是取消选中都去执行添加tag的弹窗操作
        return NO;
    }
    return YES;
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
    BOOL isExtralItem = [self.mDataSource isExtraItemIndexPath:indexPath];
    if (isExtralItem) {
        if (self.addTagBlock) {
            self.addTagBlock(self, indexPath);
        }
    }
}


#pragma mark - Private Method
/// 更新选中的 indexPath
- (void)__updateSelectedIndexPath:(NSIndexPath *)newIndexPath {
    CQTagModel *oldTagModel = [self.mDataSource dataModelAtIndexPath:self.oldSelectedIndexPath];
    CQTagModel *newTagModel = [self.mDataSource dataModelAtIndexPath:newIndexPath];
    
    // 1、indexPath就不一样了
    if ([newIndexPath isEqual:self.oldSelectedIndexPath] == NO) {
        if (self.oldSelectedIndexPath != nil) {
            [self deselectItemAtIndexPath:self.oldSelectedIndexPath animated:YES];
        }
        [self selectItemAtIndexPath:newIndexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
        _oldSelectedIndexPath = newIndexPath;
    }
    
    // 2、indexPath即使一样，tag也可能被更新了
    if ([newTagModel.name isEqualToString:oldTagModel.name] == NO) {
        _selectedTagNames = @[newTagModel.name];
        !self.selectedTagChangeBlock ?: self.selectedTagChangeBlock(self.selectedTagNames);
    }
}

@end
